package com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.modules.common.entity.SmsImportTask;
import com.xyht.sca_s.student_manage_system.modules.common.entity.SmsImportTaskDetail;
import com.xyht.sca_s.student_manage_system.modules.common.mapper.SmsImportTaskDetailMapper;
import com.xyht.sca_s.student_manage_system.modules.common.mapper.SmsImportTaskMapper;
import com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.entity.SmsEnrollmentManagementCollegeMajor;
import com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.entity.SmsEnrollmentManagementOrgSetting;
import com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.entity.SmsEnrollmentManagementTask;
import com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.entity.req.SmsEnrollmentManagementCollegeMajorBatchReq;
import com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.entity.req.SmsEnrollmentManagementCollegeMajorReq;
import com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.entity.resp.SmsEnrollmentManagementCollegeMajorResp;
import com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.entity.resp.SmsEnrollmentManagementOrgSettingResp;
import com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.mapper.SmsEnrollmentManagementCollegeMajorMapper;
import com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.mapper.SmsEnrollmentManagementOrgSettingMapper;
import com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.mapper.SmsEnrollmentManagementTaskMapper;
import com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.service.SmsEnrollmentManagementCollegeMajorService;
import com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.util.CollegeAndMajorUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.TaskDetailReason.*;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.TaskNameExample.TASK_NAME_COLLEGE_MAJOR_TASK_IMPORT;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.TaskStatus.TASK_STATUS_DONE;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.TaskStatus.TASK_STATUS_ERR;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.TaskTypeConstant.TASK_TYPE_COLLEGE_MAJOR_TASK;
import static com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.constant.AddTypeConstant.ADD_TYPE_ALL;
import static com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.constant.AddTypeConstant.ADD_TYPE_SINGLE;

/**
 * <p>
 * 专业院系招生计划表 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2024-01-15
 */
@Service
public class SmsEnrollmentManagementCollegeMajorServiceImpl extends ServiceImpl<SmsEnrollmentManagementCollegeMajorMapper, SmsEnrollmentManagementCollegeMajor> implements SmsEnrollmentManagementCollegeMajorService {
    @Resource
    private CollegeAndMajorUtil collegeAndMajorUtil;
    @Resource
    private SmsEnrollmentManagementCollegeMajorMapper smsEnrollmentManagementCollegeMajorMapper;
    @Resource
    private SmsEnrollmentManagementTaskMapper smsEnrollmentManagementTaskMapper;
    @Resource
    private SmsEnrollmentManagementOrgSettingMapper smsEnrollmentManagementOrgSettingMapper;
    @Resource
    private SmsImportTaskMapper smsImportTaskMapper;
    @Resource
    private SmsImportTaskDetailMapper smsImportTaskDetailMapper;
    @Resource
    private PlatformTransactionManager transactionManager;

    @Override
    @Transactional
    public ResponseResult addEnrollmentManagementCollegeMajor(SmsEnrollmentManagementCollegeMajorReq collegeMajorReq, String user_id) {
        if (isNullOrEmpty(collegeMajorReq.getTaskId(), collegeMajorReq.getAddType(),
                collegeMajorReq.getSchoolYear(), collegeMajorReq.getEnrollmentNum())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (!collegeMajorReq.getAddType().equals(ADD_TYPE_ALL) &&
                !collegeMajorReq.getAddType().equals(ADD_TYPE_SINGLE)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (collegeMajorReq.getAddType().equals(ADD_TYPE_SINGLE)) {
            if (isNullOrEmpty(collegeMajorReq.getCollegeId(), collegeMajorReq.getMajorId())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
        }

        SmsEnrollmentManagementTask task = smsEnrollmentManagementTaskMapper.selectById(collegeMajorReq.getTaskId());
        if (task == null) {
            return CommonResult.failed(CommonCodeEnum.ENROLLMENT_MANAGEMENT_TASK_NOT_EXIST);
        }

        //全添加
        if (collegeMajorReq.getAddType().equals(ADD_TYPE_ALL)) {
            List<SmsEnrollmentManagementOrgSettingResp> collegeList = collegeAndMajorUtil.getCollegeAndMajorList();
            if (collegeList.size() < 1) {
                return CommonResult.success();
            }

            for (SmsEnrollmentManagementOrgSettingResp college : collegeList) {
                if (college.getOrgList().size() < 1) {
                    continue;
                }

                for (SmsEnrollmentManagementOrgSettingResp major : college.getOrgList()) {
                    List<SmsEnrollmentManagementCollegeMajor> list = smsEnrollmentManagementCollegeMajorMapper.selectList(new LambdaQueryWrapper<SmsEnrollmentManagementCollegeMajor>()
                            .eq(SmsEnrollmentManagementCollegeMajor::getTaskId, collegeMajorReq.getTaskId())
                            .eq(SmsEnrollmentManagementCollegeMajor::getMajorId, major.getId())
                            .eq(SmsEnrollmentManagementCollegeMajor::getCollegeId, college.getId()));
                    if (list != null && list.size() > 0) {
                        continue;
                    }

                    SmsEnrollmentManagementCollegeMajor addCollegeMajor = new SmsEnrollmentManagementCollegeMajor();
                    addCollegeMajor.setTaskId(collegeMajorReq.getTaskId());
                    addCollegeMajor.setEnrollmentNum(collegeMajorReq.getEnrollmentNum());
                    addCollegeMajor.setCollegeId(college.getId().toString());
                    addCollegeMajor.setCollegeName(college.getOrgName());
                    addCollegeMajor.setMajorId(major.getId().toString());
                    addCollegeMajor.setMajorName(major.getOrgName());
                    addCollegeMajor.setCreateUser(user_id);
                    addCollegeMajor.setSchoolYear(collegeMajorReq.getSchoolYear());
                    smsEnrollmentManagementCollegeMajorMapper.insert(addCollegeMajor);
                }
            }
        } else {
            SmsEnrollmentManagementOrgSetting college = smsEnrollmentManagementOrgSettingMapper.selectById(collegeMajorReq.getCollegeId());
            SmsEnrollmentManagementOrgSetting major = smsEnrollmentManagementOrgSettingMapper.selectById(collegeMajorReq.getMajorId());
            if (college == null || major == null) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }

            SmsEnrollmentManagementCollegeMajor addCollegeMajor = new SmsEnrollmentManagementCollegeMajor();
            addCollegeMajor.setTaskId(collegeMajorReq.getTaskId());
            addCollegeMajor.setEnrollmentNum(collegeMajorReq.getEnrollmentNum());
            addCollegeMajor.setCollegeId(collegeMajorReq.getCollegeId());
            addCollegeMajor.setCollegeName(college.getOrgName());
            addCollegeMajor.setMajorId(collegeMajorReq.getMajorId());
            addCollegeMajor.setMajorName(major.getOrgName());
            addCollegeMajor.setCreateUser(user_id);
            addCollegeMajor.setSchoolYear(collegeMajorReq.getSchoolYear());
            smsEnrollmentManagementCollegeMajorMapper.insert(addCollegeMajor);
        }

        QueryWrapper<SmsEnrollmentManagementCollegeMajor> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("sum(enrollment_num) as num")
                .lambda()
                .eq(SmsEnrollmentManagementCollegeMajor::getTaskId, collegeMajorReq.getTaskId());
        List<Map<String, Object>> mapList = smsEnrollmentManagementCollegeMajorMapper.selectMaps(queryWrapper);
        if (mapList != null && mapList.size() > 0) {
            JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(mapList.get(0)));
            Integer totalNum = jsonObject.getInteger("num");
            SmsEnrollmentManagementTask updateTask = new SmsEnrollmentManagementTask();
            updateTask.setId(collegeMajorReq.getTaskId());
            updateTask.setTaskNum(totalNum);
            smsEnrollmentManagementTaskMapper.updateById(updateTask);
        }
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult deleteEnrollmentManagementCollegeMajor(SmsEnrollmentManagementCollegeMajorReq collegeMajorReq) {
        if (isNullOrEmpty(collegeMajorReq.getId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsEnrollmentManagementCollegeMajor collegeMajor = smsEnrollmentManagementCollegeMajorMapper.selectById(collegeMajorReq.getId());
        if (collegeMajor == null) {
            return CommonResult.failed(CommonCodeEnum.ENROLLMENT_MANAGEMENT_COLLEGE_MAJOR_NOT_EXIST);
        }

        SmsEnrollmentManagementTask task = smsEnrollmentManagementTaskMapper.selectById(collegeMajor.getTaskId());
        if (task == null) {
            return CommonResult.failed(CommonCodeEnum.ENROLLMENT_MANAGEMENT_TASK_NOT_EXIST);
        }

        SmsEnrollmentManagementTask updateTask = new SmsEnrollmentManagementTask();
        updateTask.setId(task.getId());
        updateTask.setTaskNum(task.getTaskNum() - collegeMajor.getEnrollmentNum());
        smsEnrollmentManagementTaskMapper.updateById(updateTask);

        smsEnrollmentManagementCollegeMajorMapper.deleteById(collegeMajorReq.getId());
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult updateEnrollmentManagementCollegeMajor(SmsEnrollmentManagementCollegeMajorReq collegeMajorReq) {
        if (isNullOrEmpty(collegeMajorReq.getId(), collegeMajorReq.getEnrollmentNum(),
                collegeMajorReq.getSchoolYear())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsEnrollmentManagementCollegeMajor collegeMajor = smsEnrollmentManagementCollegeMajorMapper.selectById(collegeMajorReq.getId());
        if (collegeMajor == null) {
            return CommonResult.failed(CommonCodeEnum.ENROLLMENT_MANAGEMENT_COLLEGE_MAJOR_NOT_EXIST);
        }

        SmsEnrollmentManagementTask task = smsEnrollmentManagementTaskMapper.selectById(collegeMajor.getTaskId());
        if (task == null) {
            return CommonResult.failed(CommonCodeEnum.ENROLLMENT_MANAGEMENT_TASK_NOT_EXIST);
        }

        SmsEnrollmentManagementCollegeMajor updateCollegeMajor = new SmsEnrollmentManagementCollegeMajor();
        updateCollegeMajor.setId(collegeMajorReq.getId());
        updateCollegeMajor.setEnrollmentNum(collegeMajorReq.getEnrollmentNum());
        updateCollegeMajor.setSchoolYear(collegeMajorReq.getSchoolYear());
        smsEnrollmentManagementCollegeMajorMapper.updateById(updateCollegeMajor);

        if (!collegeMajorReq.getEnrollmentNum().equals(collegeMajor.getEnrollmentNum())) {
            SmsEnrollmentManagementTask updateTask = new SmsEnrollmentManagementTask();
            updateTask.setId(task.getId());
            updateTask.setTaskNum(task.getTaskNum() - collegeMajor.getEnrollmentNum() + collegeMajorReq.getEnrollmentNum());
            smsEnrollmentManagementTaskMapper.updateById(updateTask);
        }
        return CommonResult.success();
    }

    @Override
    public ResponseResult getEnrollmentManagementCollegeMajorList(String taskId, String collegeId, String majorId, String schoolYear, Integer pageNum, Integer pageSize) {
        QueryWrapper<SmsEnrollmentManagementCollegeMajor> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SmsEnrollmentManagementCollegeMajor::getTaskId, taskId);
        if (!isNullOrEmpty(collegeId)) {
            queryWrapper.lambda().eq(SmsEnrollmentManagementCollegeMajor::getCollegeId, collegeId);
        }
        if (!isNullOrEmpty(majorId)) {
            queryWrapper.lambda().eq(SmsEnrollmentManagementCollegeMajor::getMajorId, majorId);
        }
        if (!isNullOrEmpty(schoolYear)) {
            queryWrapper.lambda().eq(SmsEnrollmentManagementCollegeMajor::getSchoolYear, schoolYear);
        }
        Page<SmsEnrollmentManagementCollegeMajor> page = new Page<>(pageNum, pageSize);
        smsEnrollmentManagementCollegeMajorMapper.selectPage(page, queryWrapper);

        List<SmsEnrollmentManagementCollegeMajorResp> list = page.getRecords()
                .stream()
                .map(collegeMajor -> {
                    SmsEnrollmentManagementCollegeMajorResp collegeMajorResp = new SmsEnrollmentManagementCollegeMajorResp();
                    BeanUtils.copyProperties(collegeMajor, collegeMajorResp);

                    return collegeMajorResp;
                })
                .collect(Collectors.toList());
        int total = (int) page.getTotal();
        return CommonResult.success(list, total);
    }

    @Override
    @Async
    public Future<ResponseResult> batchEnrollmentManagementCollegeMajor(SmsEnrollmentManagementCollegeMajorBatchReq collegeMajorBatchReq, String user_id) {
        if (isNullOrEmpty(collegeMajorBatchReq.getTaskId(), collegeMajorBatchReq.getSchoolYear())) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
        }

        if (collegeMajorBatchReq.getCollegeMajorList() == null || collegeMajorBatchReq.getCollegeMajorList().size() < 1) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
        }

        //检测招生计划
        SmsEnrollmentManagementTask task = smsEnrollmentManagementTaskMapper.selectById(collegeMajorBatchReq.getTaskId());
        if (task == null) {
            return  new AsyncResult<>(CommonResult.failed(CommonCodeEnum.ENROLLMENT_MANAGEMENT_TASK_NOT_EXIST));
        }

        //创建导入任务
        SmsImportTask smsImportTask = new SmsImportTask();
        smsImportTask.setTaskName(TASK_NAME_COLLEGE_MAJOR_TASK_IMPORT);
        smsImportTask.setUserId(user_id);
        smsImportTask.setTaskType(TASK_TYPE_COLLEGE_MAJOR_TASK);
        smsImportTaskMapper.insert(smsImportTask);
        batchAddEnrolCollegeMajor(collegeMajorBatchReq, smsImportTask.getId());
        return new AsyncResult<>(CommonResult.success());
    }

    private void batchAddEnrolCollegeMajor(SmsEnrollmentManagementCollegeMajorBatchReq collegeMajorBatchReq, String task_id) {
        int OFFSET_ROW = 2;
        int task_status = TASK_STATUS_DONE;
        for (int i = 0; i < collegeMajorBatchReq.getCollegeMajorList().size(); i++) {
            //开启事务
            DefaultTransactionDefinition dt = new DefaultTransactionDefinition();
            // 嵌套事务 PROPAGATION_REQUIRES_NEW 每次开启一个新的事务
            dt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
            // 设置嵌套事务
            TransactionStatus status = transactionManager.getTransaction(dt);
            try {
                SmsEnrollmentManagementCollegeMajorReq collegeMajorReq = collegeMajorBatchReq.getCollegeMajorList().get(i);
                if (isNullOrEmpty(collegeMajorReq.getMajorName(), collegeMajorReq.getEnrollmentNum())) {
                    transactionManager.rollback(status);
                    task_status = TASK_STATUS_ERR;
                    createTeacherImportTaskDetail(task_id, REASON_INVALID_PARAM, (i + OFFSET_ROW) + "");
                    continue;
                }

                List<SmsEnrollmentManagementOrgSetting> majorList = smsEnrollmentManagementOrgSettingMapper.selectList(new LambdaQueryWrapper<SmsEnrollmentManagementOrgSetting>()
                        .eq(SmsEnrollmentManagementOrgSetting::getOrgName, collegeMajorReq.getMajorName()));
                if (majorList == null || majorList.size() < 1) {
                    transactionManager.rollback(status);
                    task_status = TASK_STATUS_ERR;
                    createTeacherImportTaskDetail(task_id, REASON_ORG_MAJOR_NOT_EXIST, (i + OFFSET_ROW) + "");
                    continue;
                }
                SmsEnrollmentManagementOrgSetting major = majorList.get(0);

                //获取院系id和院系名
                SmsEnrollmentManagementOrgSetting college = smsEnrollmentManagementOrgSettingMapper.selectById(major.getParentId());
                if (college == null) {
                    transactionManager.rollback(status);
                    task_status = TASK_STATUS_ERR;
                    createTeacherImportTaskDetail(task_id, REASON_ORG_COLLEGE_NOT_EXIST, (i + OFFSET_ROW) + "");
                    continue;
                }

                //判断院系专业计划是否已经设置过
                //设置过就更新  没设置过就添加
                List<SmsEnrollmentManagementCollegeMajor> collegeMajorList = smsEnrollmentManagementCollegeMajorMapper.selectList(new LambdaQueryWrapper<SmsEnrollmentManagementCollegeMajor>()
                        .eq(SmsEnrollmentManagementCollegeMajor::getTaskId,collegeMajorBatchReq.getTaskId())
                        .eq(SmsEnrollmentManagementCollegeMajor::getMajorId,major.getId())
                        .eq(SmsEnrollmentManagementCollegeMajor::getCollegeId,college.getId()));
                if (collegeMajorList != null && collegeMajorList.size() > 0){
                    SmsEnrollmentManagementCollegeMajor collegeMajor = collegeMajorList.get(0);
                    SmsEnrollmentManagementCollegeMajor updateCollegeMajor = new SmsEnrollmentManagementCollegeMajor();
                    updateCollegeMajor.setId(collegeMajor.getId());
                    updateCollegeMajor.setSchoolYear(collegeMajorBatchReq.getSchoolYear());
                    updateCollegeMajor.setEnrollmentNum(collegeMajorReq.getEnrollmentNum());
                    smsEnrollmentManagementCollegeMajorMapper.updateById(updateCollegeMajor);
                }else{
                    SmsEnrollmentManagementCollegeMajor addCollegeMajor = new SmsEnrollmentManagementCollegeMajor();
                    addCollegeMajor.setEnrollmentNum(collegeMajorReq.getEnrollmentNum());
                    addCollegeMajor.setMajorId(major.getId());
                    addCollegeMajor.setMajorName(major.getOrgName());
                    addCollegeMajor.setCollegeId(college.getId());
                    addCollegeMajor.setCollegeName(college.getOrgName());
                    addCollegeMajor.setSchoolYear(collegeMajorBatchReq.getSchoolYear());
                    addCollegeMajor.setTaskId(collegeMajorBatchReq.getTaskId());
                    smsEnrollmentManagementCollegeMajorMapper.insert(addCollegeMajor);
                }
                transactionManager.commit(status);
            } catch (Exception e) {
                e.printStackTrace();
                transactionManager.rollback(status);
                task_status = TASK_STATUS_ERR;
                createTeacherImportTaskDetail(task_id, REASON_IMPORT_ERR, (i + OFFSET_ROW) + "");
            } finally {
                if (status.isNewTransaction() && !status.isCompleted()) {
                    transactionManager.commit(status);
                }
            }
        }
        SmsImportTask smsImportTask = new SmsImportTask();
        smsImportTask.setId(task_id);
        smsImportTask.setStatus(task_status);
        smsImportTaskMapper.updateById(smsImportTask);
    }

    private void createTeacherImportTaskDetail(String task_id, String reason, String row) {
        SmsImportTaskDetail smsImportTaskDetail = new SmsImportTaskDetail();
        smsImportTaskDetail.setTaskId(task_id);
        smsImportTaskDetail.setFailReason(reason);
//        smsImportTaskDetail.setFailName(name);
        smsImportTaskDetail.setFailRow(row);
        smsImportTaskDetailMapper.insert(smsImportTaskDetail);
    }

}
